#include<bits/stdc++.h>
#include<windows.h>
using namespace std;

const int PageVolume = 100; // 定义每页的大小为100
const int PageAmount = 5;  // 定义页数为5

// 打开管道
HANDLE OpenPipe(const char* pipeName) {
    // 等待命名管道可用
    if(!WaitNamedPipe(TEXT(pipeName),NMPWAIT_WAIT_FOREVER)){
        cerr<<"Connect to pipe "<<pipeName<<" failed"<<endl;
        return INVALID_HANDLE_VALUE;
    }
    // 打开管道
    HANDLE hPipe=CreateFile(
        TEXT(pipeName),
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    // 判断管道是否打开成功
    if(hPipe==INVALID_HANDLE_VALUE){
        cout<<"Open pipe "<<pipeName<<" failed"<<endl;
    }
    return hPipe;
}

// 将页框内容写入内存
void WriteToMemory(char* pBuf, const string& pageNumber, const string& contents) {
    // 计算页框在内存中的位置，并将内容写入该位置
    char* writePage = pBuf + 100 * stoi(pageNumber);
    strcpy(writePage, contents.c_str()); 
}

int main(){
    // 打开内存映射文件对象
    HANDLE hMapFile=OpenFileMapping(
        FILE_MAP_ALL_ACCESS,
        FALSE,
        TEXT("memoryMapFile")
    );
    if(hMapFile==NULL){
        cerr<<"Could not open file mapping object: "<<GetLastError()<<endl;
        return 0;
    }
    // 映射文件到进程的地址空间
    char* pBuf = static_cast<char*>(MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, PageVolume * PageAmount));
    if (pBuf == NULL) {
        cerr<<"Could not map view of file: "<<GetLastError()<<endl;
        CloseHandle(hMapFile);
        return 0;
    }
    
    // 打开管道
    HANDLE hPipe = OpenPipe("\\\\.\\Pipe\\diskPipe");
    if(hPipe==INVALID_HANDLE_VALUE){
        return 0;
    }

    HANDLE memoryPipe = OpenPipe("\\\\.\\Pipe\\memoryPipe");
    if(memoryPipe==INVALID_HANDLE_VALUE){
        return 0;
    }
    // 从worker读取逻辑块号，将逻辑块号转换为页框号，将页框号发送给worker
    vector<string> IO={"3","2","1","4","5","6","10","9","8","7"};
    string contents(101, '\0');
    string pageNumber(101, '\0');
    DWORD dwNumberOfBytesWritten=0;
    DWORD dwNumberOfBytesRead=0;
    for(const auto& block : IO){
        // 向memory发送逻辑块号
        WriteFile(hPipe,block.c_str(),block.size(),&dwNumberOfBytesWritten,NULL);
        // 接收memory发送的页框内容
        ReadFile(hPipe,&contents[0],contents.size(),&dwNumberOfBytesRead,NULL);
        // 向disk发送请求页框号
        WriteFile(memoryPipe,"askForPage",strlen("askForPage"),&dwNumberOfBytesWritten,NULL);
        // 接收disk发送的页框号
        ReadFile(memoryPipe,&pageNumber[0],pageNumber.size(),&dwNumberOfBytesRead,NULL);
        // 将页框内容写入内存
        WriteToMemory(pBuf, pageNumber, contents);
        // 打印内存内容
        cout<<"打印内存页表 : "<<endl;
        for(int i=0;i<5;i++){
            cout<<"页框 "<<i<<" : "<<pBuf+i*100<<endl;
        }
        cout<<endl;
        
        contents.assign(101, '\0');
        pageNumber.assign(101, '\0');
    }
    // 断开管道连接并关闭管道
    DisconnectNamedPipe(hPipe);
    CloseHandle(hPipe);
    DisconnectNamedPipe(memoryPipe);
    CloseHandle(memoryPipe);
    // 暂停程序，等待用户输入
    system("pause");
    return 0;
}